#-*-coding=utf8-*-

import xlrd,json
import os
import sys
import collections
import codecs

def escape_str(val):
    return val.replace('\\', '\\\\')

def strip_quote(v):
    if not isinstance(v, str):
        return v
    if (v[0] == '"' and v[-1] == '"'):
        return v.strip('"')
    return v

def try_number(v):
    if not isinstance(v, float):
        return False
    if v == int(v):
        return int(v)
    else:
        return v

# excel 只有float, 尝试转换成int
def try_int(v):
    if v == int(v):
        return int(v)
    else:
        return v

# 判断是否为json字符串
def guess_json(jstr):
    if not isinstance(jstr, str):
        return False

    if len(jstr) < 2:
        return False

    isarray = (jstr[0] == "[" and jstr[-1] == "]") 
    isobj = (jstr[0] == "{" and jstr[-1] == "}")

    return isarray or isobj

# 格式化 json 字典
def _format_dict(val, level):
    indent = '    '*level
    res = ''
    for k, v in list(val.items()):
        res = res + "\n"  

        if isinstance(v, int) or isinstance(v, float):
            res = res + indent + k + " = " + str(v)
        elif isinstance(v, list):
            res = res + indent + k + " = {" 
            res = res + _format_array(v, level + 1)
            res = res + "\n" + indent + "}"
        elif isinstance(v, dict):
            res = res + indent + k + " = {"
            res = res + _format_dict(v, level + 1)
            res = res + "\n" + indent + "}"
        else: # string ?
            if v.find('\n') != -1 :
                res = res + indent + k + ' = ' + "[[" + v + "]]"
            else:
                res = res + indent + k + ' = ' + "'" + v + "'"

        res = res + ","

    return res

# 格式化 json 数组
def _format_array(val, level):
    indent = '    '*level
    res = ''
    for v in val:
        res = res + "\n" 

        if isinstance(v, int) or isinstance(v, float):
            res = res + indent + str(v)
        elif isinstance(v, list):
            res = res + indent + "{\n"
            res = res + _format_array(v, level+1)
            res = res + "\n" + indent + "}"
        elif isinstance(v, dict):
            res = res + indent + "{"
            res = res + _format_dict(v, level + 1)
            res = res + "\n" + indent + "}" 
        else: # string ?
            if v.find('\n') != -1 :
                res = res + indent + "[[" + v + "]]" 
            else:
                res = res + indent + "'" + v + "'"

        res = res + ","

    return res


# json 字符串转为lua文本
def json2lua(jstr, level=0):
    j = json.loads(jstr)

    indent = '    '*level
    res = indent + "{\n"
    if isinstance(j, list):
        res = res + _format_array(j, level + 1)
    elif isinstance(j, dict):
        res = res + _format_dict(j, level + 1)
    else:
        assert("unknown type")
    res = res + "\n" + indent + "}"
    return res

'''
 excel 表转成 lua文件 
 |output| : 输出的lua文件名
 |ignore| : 忽略的列
'''
def excel2lua(excel_file, output, ignore=[]):
    print("exec file_name:%s" % excel_file)
    book = xlrd.open_workbook(filename=excel_file)
    sh = book.sheet_by_index(0)

    if sh.nrows < 3:
        print("{0} parse config failed: need more than 3 lines".format(excel_file))
        os.exit()

    type_hint = []
    fields = []
    comments = []
    for colx in range(0, sh.ncols):
        type_hint.append(sh.cell(0, colx).value)
        fields.append(sh.cell(1, colx).value)
        comments.append(sh.cell(2, colx).value)

    luastr = "return {\n"

    for r in range(3, sh.nrows):
        item = "    {\n"
        for c in range(0, sh.ncols):
            field = fields[c]
            if field in ignore:
                continue
            try:
                cell = sh.cell(r,c)
                # print(field, cell.value, cell.ctype)
                val = cell.value
                if type_hint[c] in ["int", "long"]:
                    item = item + "        {field} = {value}, \n".format(field=field, value=int(val))
                elif type_hint[c] in ["float", "double"]:
                    item = item + "        {field} = {value}, \n".format(field=field, value=float(val))
                elif type_hint[c] == "string":
                    if try_number(val):
                        val = str(try_int(val))
                    item = item + "        {field} = '{value}',\n".format(field=field, value=escape_str(val))
                elif type_hint[c] == "json":
                    val = cell.value.encode('utf8')
                    item = item + "        {field} = \n{value},\n".format(field=field, value=json2lua(val, 2))
                elif type_hint[c] == "any":
                    if guess_json(cell.value):
                        val = cell.value.encode('utf8')
                        item = item + "        {field} = \n{value},\n".format(field=field, value=json2lua(val, 2))
                    elif try_number(cell.value):
                        item = item + "        {field} = {value},\n".format(field=field, value= try_number(cell.value))
                    else: # string ?
                        # print "没有支持类型"
                        #val = cell.value.encode('utf8')
                        val = strip_quote(val)
                        item = item + "        {field} = '{value}',\n".format(field=field, value=val)

            except Exception as e:
                print("error ! row:%s,column:%s, err=%s" % (r+1, c, e))
                print(cell.value)
                exit()

        item = item + "    },\n"
        luastr = luastr + item

    luastr = luastr + "}"

    with codecs.open(output, 'w', 'utf-8') as f:
        f.write(luastr.replace("\n", "\r\n"))

def main():
    cfg_file_name = collections.OrderedDict()
    get_transfer_name(cfg_file_name)
    excel_dir = sys.argv[1]
    output_dir = sys.argv[2]

    for excel_name, item in list(cfg_file_name.items()):
        output_name = item[0] # 输出lua文件名
        ignore_col = item[1] # 不输出到lua文件里的列名
        excel_file_path = excel_dir + excel_name
        output_file_path = os.path.join(output_dir, output_name)
        #print("excel_file_path name:%s, output_file_path:%s" % (excel_file_path, output_file_path))
        output_path = os.path.dirname(output_file_path)
        #print("output_path:%s" % output_path)
        if not os.path.exists(output_path):
            #print("Crate path:%s" % output_path)
            os.makedirs(output_path)

        excel2lua(excel_file_path, output_file_path, ignore_col)

def test():
    jstr1 = '[{"id":1, "quantity":12},{"id":1, "quantity":12}]'
    #print(json2lua(jstr1, 0))
    jstr1 = '["1213", "badf", [1,2], {"id":1, "quantity":["ab", 1,3]},{"id":1, "quantity":12}]'
    #json2lua(jstr1, 0)
    print((json2lua(jstr1)))

def get_transfer_name(cfg_file_name):
    file_path = "./transfer_file_name.txt"
    for line in open(file_path, "r"):
        str_line = line.strip()
        if not len(str_line):
            continue

        if str_line == "[file_name]":
            continue

        names = str_line.split()
        if names[0] == "source_name":
            continue
        if len(names) < 2:
            print('parse line failed,', str_line)
            sys.exit(1)

        sn = names[0]
        on = names[1]
        # 从第3个参数开始表示忽略掉的列名
        cfg_file_name[sn] = [on, names[2:]]

if __name__ == "__main__":
    main_version = int(sys.winver.split(".")[0])
    if main_version == 3:
        main()
    else:
        print("Use Python 3!")

